package com.google.code.p.restrpc.mon.web;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.code.p.restrpc.mon.web.client.ClientMonitor;
import com.google.code.p.restrpc.mon.web.registry.RegistryMonitor;
import com.google.code.p.restrpc.mon.web.server.ServerMonitor;

/**
 * No security filter provided,please integrate this with your application's
 * filter. i.e. add spring-security filter to protect the servlet
 * 
 * @author dz
 */
public class RestRpcHttpServlet extends AbstractHttpServlet {
    
    private final static Log logger = LogFactory.getLog(RestRpcHttpServlet.class);
    
    protected final static String WEB_RESOURCE_PATH = "META-INF/mon/web";
    
    private Map<String, ServiceDispatcher> dispatchers;
    
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        // register the ServiceDispatcher
        dispatchers = new HashMap<String, ServiceDispatcher>();
        dispatchers.put("server", new AbstractServiceDispatcher() {
            
            private ServerMonitor serviceObject = new ServerMonitor();
            
            @Override
            public Object getServiceObject() {
                return serviceObject;
            }
            
        });
        
        dispatchers.put("registry", new AbstractServiceDispatcher() {
            
            private RegistryMonitor serviceObject = new RegistryMonitor();
            
            @Override
            public Object getServiceObject() {
                return serviceObject;
            }
            
        });
        
        dispatchers.put("client", new AbstractServiceDispatcher() {
            
            private ClientMonitor serviceObject = new ClientMonitor();
            
            @Override
            public Object getServiceObject() {
                return serviceObject;
            }
            
        });
        
    }
    
    @Override
    protected URI getServletCodeSourceLocation() throws URISyntaxException {
        return RestRpcHttpServlet.class.getProtectionDomain()
                                       .getCodeSource()
                                       .getLocation()
                                       .toURI();
    }
    
    @Override
    protected String getWebResourcePath() {
        return WEB_RESOURCE_PATH;
    }
    
    @Override
    protected InputStream getResourceAsStream(String filePath) {
        return RestRpcHttpServlet.class.getClassLoader()
                                       .getResourceAsStream(filePath);
    }
    
    @Override
    protected boolean isDynamicRequest(String requestPath,
                                       HttpServletRequest request,
                                       HttpServletResponse response) throws ServletException,
                                                                    IOException {
        if (StringUtils.isEmpty(requestPath)) {
            return false;
        }
        return requestPath.indexOf(".json") >= 0;
    }
    
    @Override
    protected void serviceDynamicRequest(String requestPath,
                                         HttpServletRequest request,
                                         HttpServletResponse response) throws ServletException,
                                                                      IOException {
        int posOfSlash = requestPath.indexOf("/", 1);
        if (posOfSlash <= 0) {
            response.setStatus(404);
            return;
        }
        String moduleName = requestPath.substring(1, posOfSlash);
        String methodName = requestPath.substring(posOfSlash + 1,
                                                  requestPath.indexOf(".json"));
        
        ServiceDispatcher dispatcher = dispatchers.get(moduleName);
        if (dispatcher == null) {
            response.setStatus(404);
            return;
        }
        response.setContentType("application/json;charset=utf-8");
        response.getWriter()
                .print(dispatcher.dispatch(methodName,
                                           request.getParameterMap()));
        response.getWriter().flush();
    }
    
}
